#pragma once
#include <string>
#include <iostream>
#include <unordered_map>
#include <memory>
#include "Connection.hpp"
#include "Epoll.hpp"
// 我们需要管理链接
// 在这里我们把这个TcpServer就看作一个Reactor
class Reactor
{
private:
    bool IsEXist(std::shared_ptr<Connection> &socket)
    {
        auto pos = _connections.find(socket->Sockfd());
        return pos != _connections.end();
    }
    bool IsEXist(int fd)
    {
        auto pos = _connections.find(fd);
        return pos != _connections.end();
    }

public:
    Reactor()
        : _epoller(std::make_unique<epoller>())
    {
    }
    void AddConnection(std::shared_ptr<Connection> &socket)
    {
         if (IsEXist(socket))
        {
            LOG(LogLevel::INFO) << socket->Sockfd() << " conn in Reactor!";
            return;
        }
        // 0. 让conn回指向当前reactor
       socket->SetOwner(this);
        // 1. conn 插入到 _connections
        _connections.insert(std::make_pair(socket->Sockfd(), socket));// 这里我曾经有一个错误就是map里面的第二个参数写成了unique_ptr类型，这种类型是不支持赋值的
        // 2. conn->sockfd, event 写透到内核中?-> _epoller!
        _epoller->AddEvent(socket->Sockfd(), socket->Events());
        LOG(LogLevel::INFO) << socket->Sockfd() << " conn add to Reactor";
    }
    void Looponce(int timeout)
    {
        int n = _epoller->wait(evs, timeout);
        for (int i = 0; i < n; i++)
        {
            uint32_t events = evs[i].events;
            int sockfd = evs[i].data.fd;
            // 到这里需要处理事情
            // 我们可能在epoll的时候就出现了异常，然后可能Recver或者Sender的时候也可能会出现异常
            // 为了使代码简介，可以统一报错，让他们读就绪或者写就绪，然后在读写的时候处理
            if (events & EPOLLERR)
            {
                events = EPOLLIN | EPOLLOUT;
            }
            if (events & EPOLLHUP)
            {
                events = EPOLLIN | EPOLLOUT;
            }

            // 增加代码的鲁棒性
            if (events & EPOLLIN && IsEXist(sockfd))
            {
                _connections[sockfd]->Recver();
            }
            if (events & EPOLLOUT && IsEXist(sockfd))
            {
                _connections[sockfd]->Sender();
            }
        }
    }
    void Loop() // 服务启动
    {
        int timeout = 1000;
        while (true)
        {
            Looponce(timeout);
        }
    }
    void Eablereadwirte(int sockfd ,bool Eableread , bool Eablewrite)
    {
        //1 先修改connection对象
        uint32_t events =(Eableread ? EPOLLIN : 0) |(Eablewrite ? EPOLLOUT : 0) | EPOLLET;
        _connections[sockfd]->SetEvents(events);

        //2 添加到内核里面
        _epoller->ModEvent(sockfd,events);

    }
    ~Reactor()
    {
    }

private:
    std::unordered_map<int, std::shared_ptr<Connection>> _connections;
    // 这里为什么用指针因为，我们的class Connectin 可能会有子类
    std::unique_ptr<epoller> _epoller;

    struct epoll_event evs[gsize];
};